package com.fitz.context;

import com.fitz.annotation.*;
import com.fitz.bean.BeanDefinition;
import com.fitz.bean.DefaultListableBeanFactory;
import com.fitz.bean.PropertyDefinition;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author gousili
 * Created  on 2020/7/6
 */
public abstract class AbstractApplicationContext implements ApplicationContext {

    private String packageName = "com.fitz.test";

    private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    @Override
    public void refresh() throws Exception {
        List<BeanDefinition> beanDefinitions = new ArrayList<>();
        scanner(packageName,beanDefinitions);
        beanFactory.addBeanDefines(beanDefinitions);
        beanFactory.initBeans();
        beanFactory.injectObject();
    }

    @Override
    public Object getBean(String name) {
        return beanFactory.getBean(name);
    }

    @Override
    public <T> T getBean(String name, Class<T> clazz) {
        return null;
    }

    @Override
    public boolean containsBean(String name) {
        return false;
    }

    private void scanner(String packageName, List<BeanDefinition> beanDefines){
        if (StringUtils.isNotBlank(packageName)){
            URL url = AbstractApplicationContext.class.getClassLoader().getResource(packageName.replace(".","/"));
            assert url != null;
            File dir = new File(url.getFile());
            for (File file : dir.listFiles()){
                if (file.isDirectory()){
                    scanner(packageName + "." + file.getName(),beanDefines);
                }else {
                    String className = packageName + "." + file.getName().replace(".class", "");
                    initAnnotation(className,beanDefines);
                }
            }
        }
    }

    private void initAnnotation(String className, List<BeanDefinition> beanDefines){
        try {
            String beanId = className.substring(className.lastIndexOf('.') + 1);
            Class<?> clazz = Class.forName(className);
            if (!checkAnnotation(clazz)){
                return;
            }
            System.out.println("initAnnotation: " + beanId);
            BeanDefinition beanDefinition = new BeanDefinition(beanId,className);
            //设置属性
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields){
                if (field.isAnnotationPresent(Autowired.class)){
                    //如果属性是对象
                    PropertyDefinition propertyDefinition = new PropertyDefinition(field.getName(),null,field.getName());
                    beanDefinition.addPropertyDefinition(propertyDefinition);
                }
            }
            beanDefines.add(beanDefinition);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 被这些注解标注的才是纳入bean管理
     * @param clazz
     * @return
     */
    private boolean checkAnnotation(Class<?> clazz){
        return clazz.isAnnotationPresent(Controller.class)
                || clazz.isAnnotationPresent(Service.class)
                || clazz.isAnnotationPresent(Component.class);
    }
}
